/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation
**
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
**     the names of its contributors may be used to endorse or promote
**     products derived from this software without specific prior written
**     permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** $QT_END_LICENSE$
**
****************************************************************************/



// System Includes.
#include <e32std.h>
#include <e32base.h>
#include <charconv.h>
#include <platform/collate.h>

//! User Includes.
#include "stringrenderer_symbian.h"
#include "descriptorexamples_symbian.h"

/*!
 * -----------------------------------------------------------------------------
 * These macros are shorter versions for Rendering macros. They assume variable
 * 'output' derived from TDes to be in the scope where used.
 * -----------------------------------------------------------------------------
 */
#define RenderVariableString(aVariableName) \
    RenderVariableFormatted(aVariableName, output, KRenderDefault);

#define RenderVariableBinary(aVariableName) \
    RenderVariableFormatted(aVariableName, output, KRenderContentAsBinary);

#define RenderResult(aDeclaration) \
    RenderResultFormatted(aDeclaration, output, KRenderDefault);

#define ExecuteAndRenderVariable(aDeclaration, aVariable) \
    ExecuteAndRenderVariableFormatted(aDeclaration, aVariable, output, \
                                      KRenderDefault );
/*!
 * -----------------------------------------------------------------------------
 * This example method is documented in header file "DescriptorExamples.h"
 * -----------------------------------------------------------------------------
 */
void CDescriptorExamples::NonModifyingMethods()
    {
    _LIT(KNonModifyingMethods,"NonModifyingMethods");
    TPtr output( iViewer->GetViewBuffer() );
    RenderHeader( KNonModifyingMethods, output );

    // ---------- Initialize an example string ----------
    // this declares a literal with a few characters
    _LIT(KCharacters, "abcdefghijklmnopqrstuvwxyz0123456789");
    // this casts the literal to non modifiable descriptor
    const TDesC &str = KCharacters();
    RenderVariableString(str);

    // ---------- Capacity ----------
    _LIT(KCapacityMsg,"\nCapacity...\n");
    output.Append( KCapacityMsg );

    // Length() returns number of characters in descriptor
    RenderResult( str.Length() ); // 36

    // Size() returns number of bytes in descriptor - in unicode buid it is
    //        2*Length() and in non-unicode build it is same as Length()
    RenderResult( str.Size() ); // 72

    // ---------- Extracting portions ----------
    _LIT(KExtractionMsg,"\nExtracting portions...\n");
    output.Append( KExtractionMsg );

    // Left(count) returns a string witn "count" number of characters
    // calculated from left side of the string
    RenderResult( str.Left(2) ); // "ab"
    RenderResult( str.Left(5) ); // "abcde"

    // Right(count) returns a string witn "count" number of characters
    // calculated from right side of the string
    RenderResult( str.Right(2) ); // "89"
    RenderResult( str.Right(12) ); // "yz0123456789"

    // Mid(index, count) returns a portion from string starting
    // from "index" and having "count" number of characters
    RenderResult( str.Mid(2,6) ); // "cdefgh"
    RenderResult( str.Mid(33,3) ); // "789"

    // if "count" is omitted the rest of the string from "index" is returned
    RenderResult( str.Mid(28) ); // "23456789"
    RenderResult( str.Mid(35) ); // "9"

    // ---------- Locating character ----------
    _LIT(KLocatingMsg, "\nLocating character...\n");
    output.Append( KLocatingMsg );

    // locate index of given character
    _LIT(KString, "1ABAD");
    RenderResult( str.Locate('d') ); // 3
    RenderResultFormatted( KString().Locate('A'),
        output, KRenderDefault); // "1"
    RenderResultFormatted( KString().LocateReverse('A'),
        output, KRenderDefault); // "1"

    // ---------- Compare ----------
    // Comparison with method Compare() uses the binary comparison approach to
    // compare each character in string. For example value of character
    // 'A' has unicode value of 65 and 'a' 97.
    //
    // Both strings could have been converted to lower or upper case to perform
    // case insensitive comparison. However, there exists also CompareC() method
    // below that introduces a method to compare in case insensitive manner.
    _LIT(KCompareMsg, "\nCompare()\n");
    output.Append( KCompareMsg );

    // examplerun: str.Compare(_L("aaa"))=1
    _LIT(KString1, "aaa");
    RenderResultFormatted( str.Compare( KString1 ),
        output, KRenderDefault); // >0 : str is greater

    // examplerun: str.Compare(_L("zzz"))=-25
    _LIT(KString2,"zzz");
    RenderResultFormatted( str.Compare( KString2 ),
        output, KRenderDefault ); // <0 : str is less

    // examplerun: str.Compare(str)=0
    RenderResult( str.Compare(str) );       // 0  : str is equal

    // examplerun: str.Left(2).Compare(_L("ab"))=0
    _LIT(KString3,"ab");
    RenderResultFormatted( str.Left(2).Compare(KString3),
        output, KRenderDefault); // 0 : equal

    // examplerun: str.Left(2).Compare(_L("AB"))=32
    // 'A' (65) > 'a' (97)
     _LIT(KString4,"AB");
    RenderResultFormatted( str.Left(2).Compare(KString4),
        output, KRenderDefault ); // 0 : equal

    // ---------- Comparing (Collated) ----------
    // To perform collated comparisons, method
    //
    //   CompareC(TDesC&, TInt aMaxLevel, const TCollationMethod*)
    //
    // is used. The aMaxLevel parameter can be used to perform specific rules:
    //
    // 0 - only test the character identity; accents and case are ignored
    // 1 - test the character identity and accents; case is ignored
    // 2 - test the character identity, accents and case
    // 3 - test the Unicode value as well as the character identity,
    //     accents and case.
    //
    _LIT(KCollatedCmpMsg,"\nCompareC()...\n");
    output.Append( KCollatedCmpMsg );

    // To perform case insensitive comparison, level 1 is used
    RenderResultFormatted( KString3().CompareC(KString4,1,NULL),
        output, KRenderDefault ); // 0 : equal

    // note that when using collated comparison as case sensitive manner
    // the string "ab" is less than "AB" while using standars Compare()
    // the "ab" is greater than "AB"!!!
    RenderResultFormatted( KString3().CompareC(KString4,2,NULL),
        output, KRenderDefault );
    RenderResultFormatted( KString3().Compare(KString4),
        output, KRenderDefault );

    // ----------
    // The natural comparison ignores white space differences.
    // This and other specific behaviour can be changed by modifying
    // the standard behaviour.
    TCollationMethod stdMethod = *Mem::CollationMethodByIndex(0); // std impl

    // dont ignore punctuation and spaces
    TCollationMethod strictMethod = stdMethod; // copy std impl
    strictMethod.iFlags |= TCollationMethod::EIgnoreNone; // modify copy

    // use level 1 (case ignored) in both cases to compare. Then use
    // standard method and modified one. Examplerun:
    //
    //     _LIT(KString5, "a   b");
    //     _LIT(KString6, "A B");
    //
    //    KString5.CompareC(KString6,1,&stdMethod)=0
    //    KString5.CompareC(KString6,1,&strictMethod)=-2
    //
    _LIT(KString5, "a   b");
    _LIT(KString6, "A B");
    RenderResultFormatted( KString5().CompareC(KString6,1,&stdMethod),
        output, KRenderDefault );
    RenderResultFormatted( KString5().CompareC(KString6,1,&strictMethod),
        output, KRenderDefault );

    iViewer->UpdateView();
    }
/*!
 * -----------------------------------------------------------------------------
 * This example method is documented in header file "DescriptorExamples.h"
 * -----------------------------------------------------------------------------
 */
void CDescriptorExamples::ModifyingMethodsL()
    {
    // this is used to point to correct position in view buffer
    TPtr output( iViewer->GetViewBuffer() );
    _LIT(KModifyingMethods, "ModifyingMethods");
    RenderHeader( KModifyingMethods, output );
    TBuf<10> buf10;

    // ---------- Setting and viewing characteristics ----------
    _LIT(KCharacteristicsMsg, "\nCharacteristics of buffer after initialization:\n");
    output.Append( KCharacteristicsMsg );
    RenderResult( buf10.MaxLength() ); // max number of chars
    RenderResult( buf10.MaxSize() ); // max number of bytes
    RenderResult( buf10.Length() ); // number of chars
    RenderResult( buf10.Size() ); // number of bytes

    _LIT(KHello, "Hello");
    TBuf<20> example(KHello);
    RenderVariableFormatted( example, output, KRenderCharacteristics );

    // first init the data in buffer with asterix
    _LIT(KFillMsg, "\nLet's fill the buffer\n");
    output.Append( KFillMsg );
    buf10.Fill( '*', buf10.MaxLength() );
    RenderVariableString( buf10 ); // max number of bytes
    RenderResult( buf10.Length() ); // number of chars
    RenderResult( buf10.Size() ); // number of bytes

    _LIT(KLengthManipulateMsg, "\nNow manipilate the length:\n");
    output.Append( KLengthManipulateMsg );
    // set the current length to three. The data that exist in the
    // buffer is as is
    ExecuteAndRenderVariable( buf10.SetLength(3), buf10 );
    ExecuteAndRenderVariable( buf10.SetMax(), buf10 );
    ExecuteAndRenderVariable( buf10.Zero(), buf10 );

    // ---------- Copying ----------
    _LIT(KCopyMsg, "\nCopying...\n");
    output.Append( KCopyMsg );

    _LIT8(KNarrowHello, "hello");
    TPtrC8 narrowHello( KNarrowHello );
    RenderVariableString( narrowHello );

    _LIT16(KWideHello, "unIc heLLo");
    TPtrC16 wideHello( KWideHello );
    RenderVariableString( wideHello );
    // copy contents of 8 bit descriptor to 16 bit descriptor
    ExecuteAndRenderVariable( buf10.Copy(narrowHello), buf10 );
    // copy contents of 16 bit descriptor to 16 bit descriptor
    ExecuteAndRenderVariable( buf10.Copy(wideHello), buf10 );
    // copy contents of 16 bit descriptor to 16 bit descriptor
    // and capitalize the content
    ExecuteAndRenderVariable( buf10.CopyCP(wideHello), buf10 );
    // copy and set to lower case
    ExecuteAndRenderVariable( buf10.CopyLC(wideHello), buf10 );
    // copy and set to Uppper case
    ExecuteAndRenderVariable( buf10.CopyUC(wideHello), buf10 );

    // ---------- Repeating ----------
    _LIT(KRepeatMsg, "\nRepeating...\n");
    output.Append( KRepeatMsg );

    _LIT(KaBc, "aBc");
    TPtrC abc( KaBc );
    RenderVariableString( abc );
    // write abs twise to the descriptor
    ExecuteAndRenderVariable( buf10.Repeat((TText*)abc.Ptr(),2), buf10 );
    // write abs until to the maximum size
    ExecuteAndRenderVariable( buf10.Repeat(abc), buf10 );

    // ---------- Justifying ----------
    _LIT(KJustifyMsg, "\nJustifying...\n");
    output.Append( KJustifyMsg );
    RenderVariableString( abc );
    // show aligning of string "abs" to our buffer
    ExecuteAndRenderVariable( buf10.Justify(abc,8,ELeft,'_'), buf10 );
    ExecuteAndRenderVariable( buf10.Justify(abc,8,ECenter,'*'), buf10 );
    ExecuteAndRenderVariable( buf10.Justify(abc,10,ERight,'.'), buf10 );

    // ---------- Rendering numbers ----------
    _LIT(KRenderingMsg, "\nRendering numbers...\n");
    output.Append( KRenderingMsg );
    // decimal number
    ExecuteAndRenderVariable( buf10.Num(12345), buf10 );
    // hexadecimal number. characters in lover case
    ExecuteAndRenderVariable( buf10.Num(65300,EHex), buf10 );
    // binary number
    ExecuteAndRenderVariable( buf10.Num(55,EBinary), buf10 );
    // hexadecimal number. characters in upper case
    ExecuteAndRenderVariable( buf10.NumUC(65300,EHex), buf10 );
    // fixed width decimal number
    ExecuteAndRenderVariable( buf10.NumFixedWidth(25,EDecimal,6), buf10 );
    // fixed width hexadecimal number
    ExecuteAndRenderVariable( buf10.NumFixedWidth(0xf05,EHex,6), buf10 );
    // fixed width binary number
    ExecuteAndRenderVariable( buf10.NumFixedWidth(3,EBinary,8), buf10 );
    // fixed width hexadecimal number, upper case
    ExecuteAndRenderVariable( buf10.NumFixedWidthUC(0xf05,EHex,6), buf10 );

    // declare 64 bit number that has now only lower 32 bits set
    TInt64 longNum(0x12345678);
    ExecuteAndRenderVariable( buf10.Num(longNum,EHex), buf10 );
    // multiply the result so that it needs more than 32 bits and show results.
    // The result 123456780 > FFFFFFFF that is the maximum size 32 bit
    // integer can store
    ExecuteAndRenderVariable( buf10.Num(longNum*16,EHex), buf10 );

    TRealFormat realFormatter(8);
    ExecuteAndRenderVariable( buf10.Num(3.5,realFormatter), buf10 );
    ExecuteAndRenderVariable( buf10.Num(10.0/3,realFormatter), buf10 );
    ExecuteAndRenderVariable( buf10.Num(123.0*1000*1000*1000,realFormatter),
                              buf10 );

    // ---------- Formatting ----------
    _LIT(KFormattingMsg, "\nFormatting data types\n");
    output.Append( KFormattingMsg );
    TBuf<64> buf;
    RenderVariableFormatted( buf, output, KRenderCharacteristics );

    // binary format using %b
    _LIT(KBinary, "binary=%b");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KBinary, 33),
        buf,output, KRenderDefault );

    // integer format using %d
    _LIT(KDecimal, "decimal=%d");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KDecimal, 33),
        buf,output, KRenderDefault );

    // hexadecimal format using %x
    _LIT(KHexaDecimal, "hexadecimal=%x");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KHexaDecimal, 33),
        buf,output, KRenderDefault );

    // real as exponent format
    _LIT(KRealExp, "real (exp)=%e");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KRealExp, 33.43),
        buf,output, KRenderDefault );

    // real as fixed format
    _LIT(KRealFixed, "real (fixed)=%f");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KRealFixed, 33.43),
        buf,output, KRenderDefault );

    // pointer to descriptor
    _LIT(Khellostring, "hello");
    _LIT(KString, "str='%S'");
    _LIT(KString1, "str='%s'");
    TPtrC str = Khellostring();
    RenderVariableString( str );
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString, &str),
        buf,output, KRenderDefault );

    // pointer to null terminated character array
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString1, str.Ptr()),
        buf,output, KRenderDefault );

    // ---------- Formatting align and padding ----------
    _LIT(KalignpadMsg, "\nFormatting align and padding\n");
    output.Append( KalignpadMsg );

    // padding width: 10, default pad character, default alignment
    _LIT(KString2, "binary=%10b");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString2, 33),
        buf,output, KRenderDefault );

    // padding width: 10, '0' as pad character, default alignment
    _LIT(KString3, "binary=%010b");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString3, 33),
        buf,output, KRenderDefault );

    // padding width: 8, '0' as pad character, default alignment
    _LIT(KString4, "binary=%08d");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString4, 12345),
        buf,output, KRenderDefault );

    RenderVariableString( str );
    _LIT(KString5, "str='%20S'");
    // padding width: 20, default pad character, default alignment
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString5, &str),
        buf,output, KRenderDefault );

    // padding width: 20, '0' as pad character, default alignment
    _LIT(KString6, "str='%020S'");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString6, &str),
        buf,output, KRenderDefault );

    // padding width: 20, default (space) as pad character, center alignment
    _LIT(KString7, "str='%=20S'");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString7, &str),
        buf,output, KRenderDefault );

    // padding width: 20, default (space) as pad character, left alignment
    _LIT(KSTring8, "str='%-20S'");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KSTring8, &str),
        buf,output, KRenderDefault );

    // padding width: 20, default (space) as pad character, right alignment
    _LIT(KString9, "str='%+20S'");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString9, &str),
        buf,output, KRenderDefault );

    // padding width: 20, custom pad character, center alignment
    _LIT(KString10, "str='%=*20S'");
    ExecuteAndRenderVariableFormatted(
        buf.Format( KString10, '.', &str),
        buf,output, KRenderDefault );

    // ---------- Modifying content in other means ----------
    _LIT(KOtherModificationMsg, "\nOther modifications...\n");
    output.Append( KOtherModificationMsg );
    _LIT(KStrabcd, "abcd");
    buf.Copy(KStrabcd);
    RenderVariableString( buf );

    // insert a string to middle of buffer
    _LIT(KString11, "____");
    ExecuteAndRenderVariableFormatted(
        buf.Insert( 2, KString11 ),
        buf, output, KRenderDefault );

    // replaces a portion with given string
    _LIT(KString12, "****");
    ExecuteAndRenderVariableFormatted(
        buf.Replace( 3, 2, KString12 ),
        buf, output, KRenderDefault );

    // _LIT(KStrAA, "AA");
    // replaces but since portion size is 0, this is same
    // as insert( 1, KStrAA );
    _LIT(KStrAA, "AA");
    ExecuteAndRenderVariableFormatted(
        buf.Replace( 1, 0, KStrAA ),
        buf, output, KRenderDefault );

    // replaces a portion but since no data empty, this is same
    // as delete( 1, 9 );
    _LIT(KStrblank, "");
    ExecuteAndRenderVariableFormatted(
        buf.Replace( 2, 9, KStrblank ),
        buf, output, KRenderDefault );

    // delete from index 1, 2 characters
    _LIT(KStrHello, "Hello!");
    buf.Copy( KStrHello);
    RenderVariableString(buf);
    ExecuteAndRenderVariableFormatted(
        buf.Delete( 1, 2 ),
        buf, output, KRenderDefault );

    // ---------- Trimming ----------
    _LIT(KTrimMsg, "\nTrimming. The buf in each case is\n");
    _LIT(KStrHelloWorld, "    Hello   World!  ");
    output.Append( KTrimMsg );
    buf.Copy( KStrHelloWorld );
    RenderVariableString(buf);

    // trim from left
    ExecuteAndRenderVariableFormatted(
        buf.TrimLeft(),
        buf, output, KRenderDefault );

    // trim from right
    buf.Copy( KStrHelloWorld );
    ExecuteAndRenderVariableFormatted(
        buf.TrimRight(),
        buf, output, KRenderDefault );

    // trim from left & right
    buf.Copy( KStrHelloWorld );
    ExecuteAndRenderVariableFormatted(
        buf.Trim(),
        buf, output, KRenderDefault );

    // trim from left & right & from middle
    buf.Copy( KStrHelloWorld );
    ExecuteAndRenderVariableFormatted(
        buf.TrimAll(),
        buf, output, KRenderDefault );

    // ---------- Filling ----------
    _LIT(KFillingMsg, "\nFilling...\n");
    output.Append( KFillingMsg );
    buf.Copy( KStrabcd );
    RenderVariableString(buf);
    // fill chars from zero index to current length with given char
    ExecuteAndRenderVariableFormatted(
        buf.Fill('*'),
        buf, output, KRenderCharacteristics );

    // fill chars from zero index to 11 with given char
    ExecuteAndRenderVariableFormatted(
        buf.Fill('.', 12),
        buf, output, KRenderCharacteristics );

    // fill chars from zero index to 6 with binary zero
    ExecuteAndRenderVariableFormatted(
        buf.FillZ(6),
        buf, output, KRenderCharacteristics | KRenderContentAsBinary);

    // change content of buffer (so length changes)
    _LIT(KHey, "Hey!");
    ExecuteAndRenderVariableFormatted(
        buf.Copy( KHey ),
        buf, output, KRenderDefault);
    // fill chars from zero index to current length binary zero
    ExecuteAndRenderVariableFormatted(
        buf.FillZ(),
        buf, output, KRenderCharacteristics | KRenderContentAsBinary);

    // ---------- Filling ----------
    _LIT(KTxtConvertMsg, "\nText conversions...\n");
    _LIT(KHelloWorld, "Hello World");
    output.Append( KTxtConvertMsg );
    buf.Copy( KHelloWorld );
    RenderVariableString(buf);
    ExecuteAndRenderVariableFormatted(
        buf.LowerCase(),
        buf, output, KRenderDefault);

    ExecuteAndRenderVariableFormatted(
        buf.UpperCase(),
        buf, output, KRenderDefault);

    ExecuteAndRenderVariableFormatted(
        buf.Capitalize(),
        buf, output, KRenderDefault);

    // ---------- Swapping ----------
    _LIT(KSwapMsg, "\nSwapping...\n");
    output.Append( KSwapMsg );
    _LIT(Kbuf1, "buf1!");
    _LIT(Kbuf2, "buf2**");
    TBuf<20> buf1( Kbuf1 );
    TBuf<20> buf2( Kbuf2 );
    RenderVariableString( buf1 );
    RenderVariableString( buf2 );
    _LIT(KSwapResult, "After buf1.Swap(buf2)\n");
    output.Append( KSwapResult );
    buf1.Swap(buf2);
    RenderVariableString( buf1 );
    RenderVariableString( buf2 );

    // ---------- AppendXXX ----------
    // AppendXXX() methods are similar like other methods in descriptor API.
    // They just append to the end of the descriptor buffer instead of
    // replacing the current content. That's why appending methods are not
    // described here.

    iViewer->UpdateView();
    }
/*!
 * -----------------------------------------------------------------------------
 * This example method is documented in header file "DescriptorExamples.h"
 * -----------------------------------------------------------------------------
 */
void CDescriptorExamples::CharacterConversionsL()
    {
{
    // Create session to the file server
    RFs fsSession;
    User::LeaveIfError( fsSession.Connect() );
    CleanupClosePushL(fsSession);

    // Create character converter that can convert between
    // SMS encoding and UCS-2
    CCnvCharacterSetConverter *converter;
    converter = CCnvCharacterSetConverter::NewLC();
    converter->PrepareToConvertToOrFromL(KCharacterSetIdentifierSms7Bit,
                                         fsSession );

    // Declare descriptor containing a string encoded with
    // 7-bit SMS encoding.
    const TUint8 SMSSourceBytes[] =
        {
        54,      // character '6'  (takes one byte)
        2,       // character '$'  (takes one byte)
        27, 61,  // character '~'  (takes two bytes)
        53,      // character '5'  (takes one byte)
        27, 101, // euro character (takes two bytes)
        };
    TPtrC8 SMSEncodedStr(SMSSourceBytes,sizeof(SMSSourceBytes));

    // Convert the SMS encoded message to the UCS-2 encoding
    TInt state = CCnvCharacterSetConverter::KStateDefault;
    TBuf<64> UCS2Buf;
    converter->ConvertToUnicode(UCS2Buf, SMSEncodedStr, state);

    // remove objects from the cleanup stack
    CleanupStack::PopAndDestroy(2); // converter, fsSession
}
    // this is used to point to correct position in view buffer
    TPtr output( iViewer->GetViewBuffer() );
    CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* sets;
    RFs fsSession;
    CCnvCharacterSetConverter *converter;

    // ---------- List available converters ----------
    // This example lists all character sets converters available in the
    // system.
    _LIT(KConvertersList, "CharacterConversions: List converters");
    RenderHeader( KConvertersList, output );

    // open connection to file server and push the instance to the cleanup
    // stack
    User::LeaveIfError(fsSession.Connect());
    CleanupClosePushL(fsSession);
    // get list of character sets and push it to cleanup stack
    sets = CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(fsSession);
    CleanupStack::PushL(sets);
    // show names
    _LIT(KList, "\nList of available character converters:\n");
    output.Append( KList );
    _LIT(KName, "  %S\n");
    for( int i=sets->Count()-1; i>=0; i-- )
    {
        TPtrC name = sets->At(i).Name();
        output.AppendFormat( KName, &name );
    }

    // ---------- Convert from 7-bit SMS to Unicode ----------
    // This example converts SMS to Unicode string.
    //
    // SMS character set consist of characters whose value is specified with 7
    // bits. So 128 characters are available in 7-bit SMS character set (default
    // alphabet). However, character set is extended so that if a character in
    // message is ESC (0x1B) the next character is treated as extended character
    // outside the default alphabet. So 7-bit SMS encoding can represent 255
    // different characters when using extended behaviour.
    //
    // The default alphabet is specified in ETSI "GSM 03.38". However, to
    // quickly view standard characters and extended ones, refer to
    // (http://www.ozeki.hu/index.phtml?ow_page_number=137) or to
    // (http://www.csoft.co.uk/character_sets/gsm.htm) or google with search
    // string "GSM character set" or "SMS character set".
    //
    // GSM 03.38 specification specifies that SMS message can be encoded with
    // four character encodings. This example codes the string with default
    // 7-bit SMS alphabet. SMS can consist of maximum of 160 characters. Packing
    // mechanism specified in GSM 03.38 makes it possible to pack 160 7-bit
    // characters to 140 bytes.
    //
    // Symbian provices character conversion for SMS 7-bit SMS data. However, it
    // doesn't use packed format specified in GSM 03.38. Instead, it treats the
    // binary array (of 8 bit numbers) to store 7 bit SMS characters.
    //
    // Lets assume that we have a SMS that consist of string "6$~5e" (where the
    // 'e' is meant to be an euro sign). The SMS and Unicode character codes for
    // the characters are:
    //
    // char | SMS value (7bit) | Unicode value (16 bit)
    // ------------------------------------------------
    // '6'  |  54              |   54
    // '$'  |   2              |   36
    // '~'  |  27              |  126 // Extended character coded
    //      |  61              |      // with two 7 bit values: ESC+code
    // '5'  |  53              |   53
    // 'e'  |  27              | 8364 // "Euro sign": Extended character
    //      | 101              |      // coded with two 7 bit values: ESC+code
    //
    const TUint8 SMSSourceBytes[] =
        {
        54,2,27,61,53,27,101
        };

    // create converter that converts character data between 7-bit GSM data and
    // Unicode
    converter = CCnvCharacterSetConverter::NewLC();
    converter->PrepareToConvertToOrFromL( KCharacterSetIdentifierSms7Bit,
                                          fsSession );

    // declare output buffer and declare a 8 bit descriptor to describe our
    // 7-bit SMS data.
    TInt state = CCnvCharacterSetConverter::KStateDefault;
    TBuf16<10> unicodeConverted;
    TPtrC8 SMSSource( SMSSourceBytes, sizeof( SMSSourceBytes ) );

    // convert the 7-bit SMS data to Unicode characters and store results to
    // variable "unicodeConverted"
    converter->ConvertToUnicode( unicodeConverted, SMSSource, state );

    // show unicode string converted from SMS ("6$~5�");
    _LIT(KMsg1, "CharacterConversions: SMS to Unicode");
    RenderHeader( KMsg1, output );
    _LIT(KMsg2, "SMS data consist of 7 bit character values (where euro and tilde char consist of two numbers):\n");
    output.Append( KMsg2 );
    RenderVariableBinary( SMSSource );
    _LIT(KMsg3, "\nWhile unicode uses 16 bits to store each character:\n");
    output.Append( KMsg3 );
    RenderVariableBinary( unicodeConverted );
    RenderVariableString( unicodeConverted );

    // ---------- Unicode To SMS ----------
    // Declare unicode string that consist "normal" and special characters
    _LIT(KMsg4, "CharacterConversions: Unicode to SMS");
    RenderHeader( KMsg4, output );
    
    //nice characters but can't be compiled with GCCE ;)
    _LIT(KUnicodeSrc, "Some nice chars: \x00F6,\x00E4,\x004F,\x00C4 \x20AC");
    TBuf<64> unicodeSource( KUnicodeSrc );
    
    //� == 00F6 
    //� == 004F
    //� == 00E4
    //� == 00C4
    
    RenderVariableString( unicodeSource ); 
    
    RenderVariableBinary( unicodeSource );

    // lets convert the unicode to 7 bit SMS
    TBuf8<128> convertedToSMS;
    converter->ConvertFromUnicode( convertedToSMS, unicodeSource );
    RenderVariableBinary( convertedToSMS );
    RenderVariableString( convertedToSMS );

    _LIT(KMsg5, "\nEuro character is espaced in SMS encoding so number of 'chars' differ:\n");
    output.Append( KMsg5 );
    RenderResult( unicodeSource.Length() );
    RenderResult( convertedToSMS.Length() );

    _LIT(KMsg6, "\nUnicode consist of 16 bit chars while SMS consist of 8 bit ones. Number of bytes in encodings:\n");
    output.Append( KMsg6 );
    RenderResult( unicodeSource.Size() );
    RenderResult( convertedToSMS.Size() );

    iViewer->UpdateView();
    CleanupStack::PopAndDestroy(3); // fsSession, sets, converter
    }
/*!
 * -----------------------------------------------------------------------------
 * This example method is documented in header file "DescriptorExamples.h"
 * -----------------------------------------------------------------------------
 */
void CDescriptorExamples::LexicalAnalysis()
    {
    TPtr output( iViewer->GetViewBuffer() );
    _LIT(KLexicalAnalysis, "LexicalAnalysis");
    RenderHeader( KLexicalAnalysis, output );

    // TLex provides methods for parsin text. Its usage is quite well
    // documented in symbian documentation "Using TLex". However, converting
    // strings to numbers is not explained. So this example explains them.
    TLex lex;

    _LIT(KNum1, "-254 is number");
    TInt num1;
    lex.Assign( KNum1 );
    RenderVariableString(lex.Remainder());
    // parse integer number
    ExecuteAndRenderVariableFormatted(
        lex.Val(num1),
        num1, output, KRenderDefault );

    _LIT(KNum2, "2ff is hex number");
    TUint32 num2;
    lex.Assign( KNum2 );

    RenderVariableString(lex.Remainder());
    // parse hex number
    ExecuteAndRenderVariableFormatted(
        lex.Val(num2, EHex),
        num2, output, KRenderDefault );

    // parse float
    _LIT(KNum3, "234.678 is real number");
    TReal32 num3;
    lex.Assign( KNum3 );
    RenderVariableString(lex.Remainder());
    // parses the value as 234.677993774414!
    lex.Val(num3, '.');
    _LIT(KNum3Value, "lex.Val(num3, '.') -> num3=");
    output.Append( KNum3Value );
    TRealFormat realFormat;
    output.AppendNum( num3, realFormat );

    iViewer->UpdateView();
    }
